//-----------------------------------------------------------------------
// <copyright file="CreateSateliteAssembliesFromResx.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Stuart</author>
// <email>stuartri</email>
// <date>2004-07-20</date>
// <summary>CreateSateliteAssemblies</summary>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks
{
    using System;
    using System.IO;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Text;
    using System.ComponentModel;
    using System.Diagnostics;
    using Microsoft.Build.Framework;
    /// <summary>
    /// Summary description for CreateSateliteAssembliesFromResx.
    /// </summary>
    public class CreateSateliteAssembliesFromResx : TaskBase
    {

        private string publicKeyFile;
        private string publicAndPrivateKeyFile;
        private string pathToTemplateDll;
        private string outputRootAssemblyName;
        private string outputRootAssemblyPath;
        private string pathToFrameworkTools;
        private string sourceCodeRootPath;
        private string pathToResGen;

        public CreateSateliteAssembliesFromResx()
        {

        }

        /// <summary>
        /// This method will find all resx files from the source code root.
        /// It will generate a satelite assembly for each culture folder found and copy to a folder of the same culture name, creating if needed, in the deployAssemblyRootPath folder.
        /// The leaf folder name MUST be a valid .NET locale. (or 'CY')
        /// 
        /// 1.For example - > a resx file in c:\sourceroot\en-gb\Microsoft.Sdc.Exceptions.DatabaseViolation.resx
        /// 2.Call method with c:\sourceroot as source path and c:\mainassemblies as deployAssemblyRoot and Microsoft.Sdc.Exceptions as assemblyRootName
        /// 
        /// 3.An assembly is created marked with the en-gb locale at location c:\mainassemblies\en-gb called Microsoft.Sdc.Exceptions.resources.dll
        ///  
        /// </summary>
        protected override void InternalExecute()
        {
            if (PathToResGen == null || PathToResGen.Length < 3) throw new TaskException("Satelite.Resgen.Path");
            if (OutputRootAssemblyPath == null || OutputRootAssemblyPath.Length < 3) throw new TaskException("Satelite.OutputRootAssemblyPath");
            if (SourceCodeRootPath == null || SourceCodeRootPath.Length < 3) throw new TaskException("Satelite.SourceCodeRootPath");
            if (OutputRootAssemblyName == null || OutputRootAssemblyName.Length < 5) throw new TaskException("Satelite.OutputRootAssemblyName");
            if (this.PathToFrameworkTools == null || this.PathToFrameworkTools.Length < 5) throw new TaskException("Satelite.PathToFrameworkTools");
            string[] directories = null;
            directories = Directory.GetDirectories(sourceCodeRootPath); //,*.resx);
            Hashtable hashTable = new Hashtable();
            Process proc = null;
            ProcessStartInfo startInfo = null;
            if (directories != null)
            {

                foreach (string directory in directories)
                {

                    string directoryName = directory;
                    string[] directoryHierarchy = directoryName.Split(Path.DirectorySeparatorChar);
                    string cultureFolder = directoryHierarchy[directoryHierarchy.Length - 1].Trim();
                    bool badCultureFlag = false;
                    try
                    {
                        if (cultureFolder.ToUpper() == "CY-GB")
                        {
                            //welsh locale - not a .Net locale but probably something we wish to support
                        }
                        else
                        {
                            CultureInfo culture = new CultureInfo(cultureFolder);
                        }
                    }
                    catch (ArgumentException)
                    {
                        badCultureFlag = true;
                    }
                    if (!badCultureFlag)
                    {
                        //make the satelite assembly for
                        //directoryName
                        //
                        string[] resxFiles = Directory.GetFiles(directoryName, "*.resx");
                        //al /t:lib /embed:strings.de.resources /culture:de /out:MyApp.resources.dll /template:MyApp.dll
                        StringBuilder sb = new StringBuilder();
                        sb.Append("/t:lib ");
                        foreach (string file in resxFiles)
                        {
                            string paramToResGen = "/compile " + "\"" + file + "\"";
                            Log.LogMessage(MessageImportance.Normal, String.Format(CultureInfo.InvariantCulture, "Calling resgen with : " + paramToResGen));

                            startInfo = new ProcessStartInfo(Path.Combine(this.PathToResGen, "resgen.exe"), paramToResGen);
                            startInfo.CreateNoWindow = true;
                            startInfo.UseShellExecute = false;
                            startInfo.WindowStyle = ProcessWindowStyle.Hidden;

                            proc = Process.Start(startInfo);
                            proc.WaitForExit();
                            sb.Append("/embed:\"");
                            sb.Append(System.IO.Path.GetDirectoryName(file));
                            sb.Append("\\");
                            sb.Append(System.IO.Path.GetFileNameWithoutExtension(file));
                            sb.Append(".resources");
                            sb.Append("\" ");
                        }
                        sb.Append("/culture:");
                        sb.Append(cultureFolder);
                        sb.Append(" /out:\"");
                        int lengthOfPath = this.OutputRootAssemblyPath.Length;
                        int foundAt = this.OutputRootAssemblyPath.IndexOf(Path.DirectorySeparatorChar, lengthOfPath - 1);
                        string tempOutputRootAssemblyPath = this.OutputRootAssemblyPath;
                        if (foundAt != -1)
                        {
                            tempOutputRootAssemblyPath = this.OutputRootAssemblyPath.Remove(lengthOfPath - 1, Path.DirectorySeparatorChar.ToString().Length);
                        }

                        if (!Directory.Exists(Path.Combine(tempOutputRootAssemblyPath, cultureFolder)))
                        {
                            Directory.CreateDirectory(Path.Combine(tempOutputRootAssemblyPath, cultureFolder));
                        }

                        string outputAssemblyPath = System.IO.Path.Combine(Path.Combine(tempOutputRootAssemblyPath, cultureFolder), this.OutputRootAssemblyName + ".resources" + ".dll");
                        if (outputAssemblyPath != null)
                        {
                            sb.Append(outputAssemblyPath);
                            sb.Append("\"");
                        }
                        else
                        {
                            throw new TaskException("Satelite.Parameters");
                        }

                        //we have the basic command - now add the strong name support options


                        if (this.PublicKeyFile != String.Empty)
                        {
                            if (this.PublicKeyFile == null || this.PublicKeyFile.Length < 3) throw new ArgumentException("Keyfile must be set for delaysign");
                            sb.Append(" /delaysign+ /keyfile:\"");
                            sb.Append(this.PublicKeyFile);
                            sb.Append("\"");

                        }
                        else if (this.PublicAndPrivateKeyFile != String.Empty)
                        {
                            if (this.PublicAndPrivateKeyFile == null || this.PublicAndPrivateKeyFile.Length < 3) throw new ArgumentException("PublicAndPrivateKeyFile must be set for signing");
                            sb.Append(" /delaysign+ /keyname:\"");
                            sb.Append(this.PublicAndPrivateKeyFile);
                            sb.Append("\"");
                        }
                        Log.LogMessage(MessageImportance.Normal, String.Format(CultureInfo.InvariantCulture, "using al to create satelite assembly. " + sb.ToString()));

                        startInfo = new ProcessStartInfo(Path.Combine(this.pathToFrameworkTools, "al.exe"), sb.ToString());
                        startInfo.CreateNoWindow = true;
                        startInfo.UseShellExecute = false;
                        startInfo.WindowStyle = ProcessWindowStyle.Hidden;

                        proc = Process.Start(startInfo);
                        proc.WaitForExit();
                    }
                }
            }
        }

        public string PublicKeyFile
        {
            get
            {
                return (publicKeyFile == null ? String.Empty : publicKeyFile);
            }
            set
            {
                publicKeyFile = value;
            }
        }

        public string PublicAndPrivateKeyFile
        {
            get
            {
                return (publicAndPrivateKeyFile == null ? String.Empty : publicAndPrivateKeyFile);
            }
            set
            {
                publicAndPrivateKeyFile = value;
            }
        }

        public string PathToTemplateDll
        {
            get
            {
                return (pathToTemplateDll == null ? String.Empty : pathToTemplateDll);
            }
            set
            {
                pathToTemplateDll = value;
            }
        }

        public string OutputRootAssemblyName
        {
            get
            {
                return (outputRootAssemblyName == null ? String.Empty : outputRootAssemblyName);
            }
            set
            {
                outputRootAssemblyName = value;
            }
        }

        public string OutputRootAssemblyPath
        {
            get
            {
                return (outputRootAssemblyPath == null ? String.Empty : outputRootAssemblyPath);
            }
            set
            {
                outputRootAssemblyPath = value;
            }
        }

        public string PathToFrameworkTools
        {
            get
            {
                return (pathToFrameworkTools == null ? String.Empty : pathToFrameworkTools);
            }
            set
            {
                pathToFrameworkTools = value;
            }
        }

        public string SourceCodeRootPath
        {
            get
            {
                return (sourceCodeRootPath == null ? String.Empty : sourceCodeRootPath);
            }
            set
            {
                sourceCodeRootPath = value;
            }
        }

        public string PathToResGen
        {
            get
            {
                return (pathToResGen == null ? String.Empty : pathToResGen);
            }
            set
            {
                pathToResGen = value;
            }
        }

    }
}

